package edu.bbte;

public class SolveCube2 {
	private Matrix3D [] pieces3D;;
	private Matrix3D [] solutions3D;
	private int nrPieces;
	private MatrixCube [] piecesCube;
	private MatrixCube solution;
	private int size;
	private boolean used[];
	private int lepes=0;
	private boolean end=false;
	
	
	public SolveCube2(Matrix3D [] pieces3D, int nrPieces) {
		this.pieces3D = pieces3D;
		this.nrPieces = nrPieces;
		
		size = pieces3D[0].getSize();
		solutions3D = new Matrix3D[nrPieces];
		piecesCube = new MatrixCube[nrPieces];
		solution = new MatrixCube(size);
		used = new boolean[nrPieces];
		for (int i=0; i < nrPieces; ++i) {
			//pieces3D[i].printMatrix();
			piecesCube[i] = new MatrixCube(size);
			piecesCube[i].setCube(this.pieces3D[i]);
			piecesCube[i].setLevel();
		}
		solutions3D[0] = new Matrix3D(size);
		solutions3D[0] = pieces3D[0];
		solution.setCube(solutions3D[0]);
		used[0] = true;
	}
	
	public void solve() {
		++lepes;
		if (allPiecesUsedUp()) {
			System.out.println("Megvan a megoldas!");
			solution.getCube().printMatrix();
			end=true;
		}
		else
		{
			int id=0;
			while(!allPiecesUsedUp()){
				boolean found=false;
				id=nextUnusedPiece(id);
				if(id==0){System.out.println("Gaz van!");}
				used[id]=true;
				MatrixCube [] pieceRotations = piecesCube[id].listOfCubeRotations();
				for(int r=0; r<24; r++){
					MatrixCube [] pieceShifts = pieceRotations[r].listOfCubeShifts(size-1, size-1, size-1, size-1, size-1, size-1);
					for(int s=0; s<pieceShifts.length; s++)
						if (solution.canAddCubes(pieceShifts[s])) {
							found=true;
							System.out.println("ID:"+id+" rot:"+r+" shift:"+s);
							solution.sumCube(pieceShifts[s]);
							//solution.printAll();
							solve();
							if(end)
								return;
							else
								solution.differenceCube(pieceShifts[s]);
						}

				}
				if(!end)
					used[id]=false;
				if(!found)
					return;
			}
		}

	}
	
	public void solve2() {
		++lepes;
		if (allPiecesUsedUp()) {
			System.out.println("Megvan a megoldas!");
			solution.getCube().printMatrix();
			end=true;
		}
		else
		{
			int id=nextUnusedPiece(0);
			if(id==0){System.out.println("Gaz van!");}
			used[id]=true;
			MatrixCube [] pieceRotations = piecesCube[id].listOfCubeRotations();
			for(int r=0; r<24; r++){
				MatrixCube [] pieceShifts = pieceRotations[r].listOfCubeShifts(size-1, size-1, size-1, size-1, size-1, size-1);
				for(int s=0; s<pieceShifts.length; s++)
					if (solution.canAddCubes(pieceShifts[s])) {
						System.out.println("ID:"+id+" rot:"+r+" shift:"+s);
						solution.sumCube(pieceShifts[s]);
						//solution.printAll();
						solve2();
						if(end)
							return;
						else
							solution.differenceCube(pieceShifts[s]);
					}

				}
				if(!end)
					used[id]=false;
				return;
		}

	}
	
	public void solve3(int index) {
		if (allPiecesUsedUp()) {
			System.out.println("Megvan a megoldas!");
			solution.getCube().printMatrix();
			end=true;
		}
		else
		{
			for(int id=1; id<nrPieces; id++)
				if((id!=index)&&(used[id]==false)){
					boolean found=false;
					used[id]=true;
					MatrixCube [] pieceRotations = piecesCube[id].listOfCubeRotations();
					for(int r=0; r<24; r++){

						Fit fit = new Fit(solution,pieceRotations[r],size);
						//MatrixCube [] pieceShifts = fit.getShiftList();
						for(int s=0; s<fit.getListLength(); s++){
							//if (solution.canAddCubes(pieceShifts[s])) {
							found=true;
								System.out.println("index:"+index+" ID:"+id+" rot:"+r+" shift:"+s);
								//solution.printAll();
								//System.out.println("Darab");
								//fit.shiftList(s).printAll();
								solution.sumCube(fit.shiftList(s));
								//System.out.println("Utana");
								//solution.printAll();
								solve3(id);
								if(end)
									return;
								else
									solution.differenceCube(fit.shiftList(s));
							}

					}
					if(!end)
						used[id]=false;
					if(!found)
						return;
				}
		}

	}

	private boolean allPiecesUsedUp() {
		for (int i=0; i<nrPieces; ++i) 
			if (!used[i])
				return false;
		return true;
	}
	
	private int nextUnusedPiece(int id){
		if(id+1<nrPieces)
			if(!used[id+1])
				return id+1;
		for (int i=0; i<nrPieces; ++i) 
			if ((!used[i])&&(i!=id))
				return i;
		return 0;
	}
	
	public Matrix3D[] getSolutions3D() {
		return solutions3D;
	}

}
